package com.lyf.scm.plan.domain.service.impl;

import cn.hutool.core.date.DateUtil;
import com.lyf.scm.common.constants.CommonConstants;
import com.lyf.scm.common.enums.*;
import com.lyf.scm.plan.api.dto.StoreInfoDTO;
import com.lyf.scm.plan.domain.convertor.BigDataBaseConvertor;
import com.lyf.scm.plan.domain.remote.bigdata.dto.BigDataGeneralInfoDTO;
import com.lyf.scm.plan.domain.remote.bigdata.dto.BigDataGeneralQueryBaseDTO;
import com.lyf.scm.plan.domain.remote.bigdata.facade.CprfCoreFacade;
import com.lyf.scm.plan.domain.remote.item.dto.CategorySimpleDTO;
import com.lyf.scm.plan.domain.remote.item.dto.SkuInfoDTO;
import com.lyf.scm.plan.domain.remote.item.facade.ItemCoreFacade;
import com.lyf.scm.plan.domain.repository.DirectlyStoreRepository;
import com.lyf.scm.plan.domain.repository.OperationLogRecordRepository;
import com.lyf.scm.plan.domain.repository.SalesPlanDirectlyRepository;
import com.lyf.scm.plan.domain.service.BigDataGeneralHandlerService;
import com.lyf.scm.plan.domain.util.BigDataCacheUtil;
import com.lyf.scm.plan.domain.util.OperationLogRecordUtil;
import com.lyf.scm.plan.insfrastructure.db.dataobject.OperationLogRecordDO;
import com.lyf.scm.plan.insfrastructure.db.dataobject.bigdata.*;
import com.rome.arch.util.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import static com.lyf.scm.plan.domain.util.BigDataCacheUtil.*;

/**
 * 大数据通用处理类（日补货接口）
 *
 * @author wangchlei
 * @date 2020/09/30
 */
@Slf4j
@Service
public class BigDataGeneralHandlerServiceImpl implements BigDataGeneralHandlerService {
    @Resource
    private RedisCacheServiceImpl redisCacheServiceImpl;
    @Resource
    private OperationLogRecordRepository operationLogRecordRepository;
    @Resource
    private DirectlyStoreRepository directlyStoreRepository;
    @Resource
    private ItemCoreFacade itemCoreFacade;
    @Resource
    private DirectlyExecuteServiceImpl directlyExecuteServiceImpl;
    @Resource
    private DirectlyStoreServiceImpl directlyStoreServiceImpl;
    @Resource
    private DemandPlanServiceImpl demandPlanServiceImpl;
    @Resource
    private SalesPlanDirectlyRepository salesPlanDirectlyRepository;
    @Resource
    private SalesPlanDirectlyAccuracyServiceImpl salesPlanDirectlyAccuracyServiceImpl;
    @Resource
    private SalePlanDirectlyDifferinServiceImpl salePlanDirectlyDifferinServiceImpl;
    @Resource
    private SalesPlanDirectlyServiceImpl salesPlanDirectlyServiceImpl;
    @Resource
    private BigDataBaseConvertor bigDataBaseConvertor;
    /**
     * 线程池
     */
    @Resource
    private ExecutorService sonExecutorService;
    /**
     * 远程调用
     */
    @Resource
    private CprfCoreFacade cprfCoreFacade;
    /**
     * 是否触发周任务
     */
    private boolean validWeekJob;
    /**
     * 标识
     */
    private String opSign;

    /**
     * 处理
     *
     * @param
     * @return void
     **/
    @Override
    public void handleApiDispatcher() {
        long startTime = System.currentTimeMillis();
        Map<String, StoreInfoDTO> storesInfo = redisCacheServiceImpl.getDirectStores();
        log.info("\n【大数据Job】：已获取所有门店,门店数量 {}", storesInfo.size());
        //初始化必要数据的缓存
        this.initCacheData();
        log.info("\n【大数据Job】：开始处理所有门店");
        storesInfo.keySet().forEach(item -> this.handleStore(storesInfo.get(item)));
        long endTime = System.currentTimeMillis();
        this.writeOperateLog(endTime - startTime);
    }

    /**
     * 初始化必要的缓存信息
     *
     * @param
     * @return void
     **/
    private void initCacheData() {
        Date date = new Date();
        //判断是否需要触发周任务
        this.validWeekJob = validWeekJob(date);
        //注入周和日的处理缓存信息
        BigDataCacheUtil.injectDayCache(date);
        BigDataCacheUtil.injectWeekCache(date);
        //数据标识
        IdWorker idWorker = new IdWorker();
        opSign = "" + idWorker.getId();
    }

    /**
     * 处理每一个门店
     *
     * @param storeInfo
     * @return void
     **/
    private void handleStore(StoreInfoDTO storeInfo) {
        //直营预测——执行（天）
        List<DirectlyExecuteInDO> directlyExecuteInDOs = new ArrayList<>();
        //直营预测计划——门店（天）
        List<DirectlyStoreInDO> directlyStoreInDOs = new ArrayList<>();
        //直营准去率（周）
        List<DirectlyAccuracyInDO> directlyAccuracyInDOs = null;
        //直营差异（周）
        List<DirectlyDifferinInDO> directlyDifferinInDOs = null;
        //直营预测（周）
        List<DirectlyInDO> directlyInDOs = null;
        if (validWeekJob) {
            //(新增) 准确率
            directlyAccuracyInDOs = new ArrayList<>();
            //(新增) 差异
            directlyDifferinInDOs = new ArrayList<>();
            //(新增) 直营预测
            directlyInDOs = new ArrayList<>();
        }
        //大数据信息
        List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs = new ArrayList<>();
        long handleStartTime = System.currentTimeMillis();
        try {
            //获取查询条件
            BigDataGeneralQueryBaseDTO bigDataGeneralQueryBaseDTO = this.getGeneralQueryBaseDTO(storeInfo.getCode(), BigDataCacheUtil.nowDate);
            //根据时间段，门店等信息  递归分页获取所有大数据信息
            this.getBigDataGeneralInfo(bigDataGeneralQueryBaseDTO, bigDataGeneralInfoDTOs);
            //合理默认两个表的状态是统一的，且其数据量数据结构是一致的（数据数量，sku,门店等是统一的）
            if (!CollectionUtils.isEmpty(bigDataGeneralInfoDTOs)) {
                if (validWeekJob) {
                    this.getDayAndWeekResult(storeInfo, bigDataGeneralInfoDTOs, directlyExecuteInDOs, directlyStoreInDOs, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs);
                } else {
                    this.getDayResult(storeInfo, bigDataGeneralInfoDTOs, directlyExecuteInDOs, directlyStoreInDOs);
                }
            } else {
                log.warn("\n【大数据Job】：门店数据无数据：code {}  name {}", storeInfo.getCode(), storeInfo.getName());
                return;
            }
        } catch (feign.RetryableException retryableException) {
            long handleEndTime = System.currentTimeMillis();
            retryableException.printStackTrace();
            log.error("\n【大数据Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + retryableException.getMessage());
            this.writeErrorLog(storeInfo.getCode(), retryableException.getMessage(), (handleEndTime - handleStartTime), bigDataGeneralInfoDTOs.size());
            return;
        } catch (Exception e) {
            long handleEndTime = System.currentTimeMillis();
            e.printStackTrace();
            log.error("\n【大数据Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5004.getMsg());
            this.writeErrorLog(storeInfo.getCode(), ResponseMsg.FAIL_5004.getMsg(), (handleEndTime - handleStartTime), bigDataGeneralInfoDTOs.size());
            return;
        }
        FutureTask<String> directlyExecuteFutureTask = new FutureTask<>(() -> {
            long sqlStartTime = System.currentTimeMillis();
            try {
                directlyExecuteServiceImpl.handleBigData(directlyExecuteInDOs, storeInfo.getCode());
            } catch (Exception e) {
                long sqlEndTime = System.currentTimeMillis();
                e.printStackTrace();
                log.error("\n【大数据（日）销售预测Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                operationLogRecordRepository.addBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_EXECUTE.getTableType(), ResponseMsg.FAIL_5005.getMsg(), directlyExecuteInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
                return "failed";
            }
            return "success";
        });
        FutureTask<String> directlyStoreFutureTask = new FutureTask<>(() -> {
            long sqlStartTime = System.currentTimeMillis();
            try {
                directlyStoreServiceImpl.handleBigData(directlyStoreInDOs, storeInfo.getCode());
            } catch (Exception e) {
                long sqlEndTime = System.currentTimeMillis();
                e.printStackTrace();
                log.error("\n【大数据（日）销售预测Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                operationLogRecordRepository.addBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_SHOP.getTableType(), ResponseMsg.FAIL_5005.getMsg(), directlyStoreInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
                return "failed";
            }
            return "success";
        });
        FutureTask<String> demandFutureTask = new FutureTask<>(() -> {
            long sqlStartTime = System.currentTimeMillis();
            try {
                demandPlanServiceImpl.handleBigData(bigDataGeneralInfoDTOs, opSign, storeInfo.getCode(), startDate1);
            } catch (Exception e) {
                long sqlEndTime = System.currentTimeMillis();
                e.printStackTrace();
                log.error("\n【大数据（日）销售预测Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                operationLogRecordRepository.addBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.PLAN_DEMAND.getTableType(), ResponseMsg.FAIL_5005.getMsg(), bigDataGeneralInfoDTOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
                return "failed";
            }
            return "success";
        });
        FutureTask<String> directlyAccuracyFutureTask = null;
        FutureTask<String> directlyDifferinFutureTask = null;
        FutureTask<String> directlyFutureTask = null;
        if (validWeekJob) {
            List<DirectlyAccuracyInDO> finalDirectlyAccuracyInDOs = directlyAccuracyInDOs;
            directlyAccuracyFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    salesPlanDirectlyAccuracyServiceImpl.handleBigData(finalDirectlyAccuracyInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据（周）销售预测Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.addBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_ACCURACY.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyAccuracyInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
                    return "failed";
                }
                return "success";
            });
            List<DirectlyDifferinInDO> finalDirectlyDifferinInDOs = directlyDifferinInDOs;
            directlyDifferinFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    salePlanDirectlyDifferinServiceImpl.handleBigData(finalDirectlyDifferinInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据（周）销售预测Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.addBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_DIFFERIN.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyDifferinInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
                    return "failed";
                }
                return "success";
            });
            List<DirectlyInDO> finalDirectlyInDOs = directlyInDOs;
            directlyFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    // salesPlanDirectlyServiceImpl.handleBigData(finalDirectlyInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据（周）销售预测Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.addBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.PLAN_DIRECTLY.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(directlyAccuracyFutureTask);
            sonExecutorService.execute(directlyDifferinFutureTask);
            sonExecutorService.execute(directlyFutureTask);
        }
        sonExecutorService.execute(directlyExecuteFutureTask);
        sonExecutorService.execute(directlyStoreFutureTask);
        sonExecutorService.execute(demandFutureTask);
        String executeFutureResult = null;
        String storeFutureResult = null;
        String demandResult = null;
        String accuracyFutureResult = "success";
        String directlyDifferinFutureResult = "success";
        String directlyFutureResult = "success";
        try {
            executeFutureResult = directlyExecuteFutureTask.get();
            storeFutureResult = directlyStoreFutureTask.get();
            demandResult = demandFutureTask.get();
            if (validWeekJob) {
                accuracyFutureResult = directlyAccuracyFutureTask.get();
                directlyDifferinFutureResult = directlyDifferinFutureTask.get();
                directlyFutureResult = directlyFutureTask.get();
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        if ("success".equals(executeFutureResult) && "success".equals(storeFutureResult) && "success".equals(demandResult) && "success".equals(accuracyFutureResult) && "success".equals(directlyDifferinFutureResult) && "success".equals(directlyFutureResult)) {
            log.info("\n【大数据Job】：门店数据处理成功：code {}  name {}", storeInfo.getCode(), storeInfo.getName());
        }
    }

    private void writeErrorLog(String storeCode, String msg, long time, int size) {
        List<OperationLogRecordDO> operationLogRecordDOs = new ArrayList<>(6);
        operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_EXECUTE.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_SHOP.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.PLAN_DEMAND.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        if (validWeekJob) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_ACCURACY.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_DIFFERIN.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.PLAN_DIRECTLY.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        operationLogRecordRepository.batchAddBigDataErrorLog(operationLogRecordDOs);
    }

    /**
     * 获取按日维度的新增更新数据
     *
     * @param storeInfo
     * @param bigDataGeneralInfoDTOs
     * @param directlyExecuteInDOs
     * @param directlyStoreInDOs
     * @return void
     **/
    private void getDayResult(StoreInfoDTO storeInfo, List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs) {
        //直营预测——执行 根据门店和日期获取所有需要更新的数据（默认为13天数据，今日起）
        List<DirectlyStoreInDO> directlyStoreDOs = directlyStoreRepository.listInByStoreAndDate(storeInfo.getCode(), BigDataCacheUtil.dayStartDate, BigDataCacheUtil.dayUpEndDate);
        if (CollectionUtils.isEmpty(directlyStoreDOs)) {
            directlyStoreDOs = new ArrayList<>(1);
        }
        //查询sku信息
        List<SkuInfoDTO> skuInfoDTOS = itemCoreFacade.skuListBySkuCodes(bigDataGeneralInfoDTOs.stream().map(BigDataGeneralInfoDTO::getSkuKey).distinct().collect(Collectors.toList()));
        Map<String, SkuInfoDTO> skuCodeName = this.getSkuInfo(skuInfoDTOS);
        Map<Integer, List<CategorySimpleDTO>> categoryInfo = this.getCategoryInfo(skuInfoDTOS);
        int count = 0;
        List<DirectlyStoreInDO> tmp = null;
        //新增sku
        String skuKey;
        BaseInDO baseInDO;
        //计数，如果不等于13算无上次预测量，直接新增即可
        for (BigDataGeneralInfoDTO bigDataGeneralInfoDTO : bigDataGeneralInfoDTOs) {
            skuKey = bigDataGeneralInfoDTO.getSkuKey();
            //直营预测————门店
            count = 0;
            tmp = new ArrayList<>();
            for (DirectlyStoreInDO storeDO : directlyStoreDOs) {
                //如果是同一条sku,默认取十三天为更新数据，第十四条为新增数据 存入集合中
                if (skuKey.equals(storeDO.getSkuCode())) {
                    //更新其同用属性（区域，品类）
                    this.setGeneralInfo(storeDO, skuKey, storeInfo, skuCodeName, categoryInfo);
                    this.setStorePredictValue(storeDO, bigDataGeneralInfoDTO);
                    tmp.add(storeDO);
                    count++;
                }
            }
            //如果含有更新数据————加入门店第十四天新增数据   执行所有新增数据,否则新增所有天数据
            baseInDO = this.createGeneralDayInDO(skuKey, storeInfo, skuCodeName, categoryInfo);
            if (count == 13) {
                directlyStoreInDOs.addAll(tmp);
                directlyStoreInDOs.add(this.getNewDirectlyStore(baseInDO, bigDataGeneralInfoDTO.getSalesDayf14()));
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf1(), day1);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf2(), day2);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf3(), day3);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf4(), day4);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf5(), day5);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf6(), day6);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf7(), day7);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf8(), day8);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf9(), day9);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf10(), day10);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf11(), day11);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf12(), day12);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf13(), day13);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf14(), day14);
            } else {
                //遍历十四天信息
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf1(), day1);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf2(), day2);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf3(), day3);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf4(), day4);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf5(), day5);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf6(), day6);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf7(), day7);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf8(), day8);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf9(), day9);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf10(), day10);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf11(), day11);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf12(), day12);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf13(), day13);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf14(), day14);
            }
        }
    }

    private void getExecuteDayDO(BaseInDO baseInDO, List<DirectlyExecuteInDO> directlyExecuteInDOs, BigDecimal sales, Date date) {
        DirectlyExecuteInDO directlyExecuteInDO = bigDataBaseConvertor.baseDOToExecuteDO(baseInDO);
        //设置日期
        directlyExecuteInDO.setFormulateDate(date);
        //设置预测量
        directlyExecuteInDO.setForecastSalesAmount(sales);
        directlyExecuteInDOs.add(directlyExecuteInDO);
    }

    /**
     * 获取直营门店第十四天的新增实体
     *
     * @return {@link DirectlyStoreInDO}
     **/
    private DirectlyStoreInDO getNewDirectlyStore(BaseInDO baseInDO, BigDecimal sales) {
        DirectlyStoreInDO newDirectlyStoreInDO = bigDataBaseConvertor.baseDOToStoreDO(baseInDO);
        newDirectlyStoreInDO.setForecastQty(sales);
        newDirectlyStoreInDO.setConfirmQty(sales);
        newDirectlyStoreInDO.setLastForecastQty(new BigDecimal("0"));
        newDirectlyStoreInDO.setLastConfirmQty(new BigDecimal("0"));
        newDirectlyStoreInDO.setFormulateDate(day14);
        return newDirectlyStoreInDO;
    }

    /**
     * 获取直营预测第十四周的新增实体
     *
     * @return {@link DirectlyStoreInDO}
     **/
    private DirectlyInDO getNewDirectly(BaseInDO baseInDO, BigDecimal sales) {
        DirectlyInDO directlyInDO = bigDataBaseConvertor.baseDOToDirectDO(baseInDO);
        directlyInDO.setForecastQty(sales);
        directlyInDO.setLastForecastQty(new BigDecimal("0"));
        directlyInDO.setPlanStartDate(startDate13);
        directlyInDO.setPlanEndDate(endDate13);
        return directlyInDO;
    }

    /**
     * 存入门店新增的更新实体
     *
     * @param storeDO
     * @return void
     **/
    private void setStorePredictValue(DirectlyStoreInDO storeDO, BigDataGeneralInfoDTO bigDataGeneralInfoDTO) {
        //获取对应日期的预测值
        Date date = storeDO.getFormulateDate();
        if (day1.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf1());
            return;
        }
        if (day2.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf2());
            return;
        }
        if (day3.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf3());
            return;
        }
        if (day4.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf4());
            return;
        }
        if (day5.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf5());
            return;
        }
        if (day6.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf6());
            return;
        }
        if (day7.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf7());
            return;
        }
        if (day8.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf8());
            return;
        }
        if (day9.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf9());
            return;
        }
        if (day10.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf10());
            return;
        }
        if (day11.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf11());
            return;
        }
        if (day12.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf12());
            return;
        }
        if (day13.equals(date)) {
            this.setDirectStoreValue(storeDO, bigDataGeneralInfoDTO.getSalesDayf13());
        }
    }

    private void setDirectlyPredictValue(DirectlyInDO directlyInDO, BigDataGeneralInfoDTO bigDataGeneralInfoDTO) {
        //获取对应日期的预测值
        Date startDate = directlyInDO.getPlanStartDate();
        if (startDate1.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesWeekf1());
            return;
        }
        if (startDate2.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf2());
            return;
        }
        if (startDate3.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf3());
            return;
        }
        if (startDate4.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf4());
            return;
        }
        if (startDate5.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf5());
            return;
        }
        if (startDate6.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf6());
            return;
        }
        if (startDate7.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf7());
            return;
        }
        if (startDate8.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf8());
            return;
        }
        if (startDate9.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf9());
            return;
        }
        if (startDate10.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf10());
            return;
        }
        if (startDate11.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf11());
            return;
        }
        if (startDate12.equals(startDate)) {
            this.setDirectValue(directlyInDO, bigDataGeneralInfoDTO.getSalesDayf12());
        }
    }

    private void setDirectValue(DirectlyInDO directlyInDO, BigDecimal sales) {
        directlyInDO.setLastForecastQty(directlyInDO.getForecastQty());
        directlyInDO.setForecastQty(sales);
    }

    private void setDirectStoreValue(DirectlyStoreInDO storeDO, BigDecimal sales) {
        storeDO.setLastForecastQty(storeDO.getForecastQty());
        storeDO.setForecastQty(sales);
        storeDO.setLastConfirmQty(storeDO.getConfirmQty());
        storeDO.setConfirmQty(sales);
    }

    private void getDayAndWeekResult(StoreInfoDTO storeInfo, List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, List<DirectlyInDO> directlyInDOs) {
        //直营预测——执行 根据门店和日期获取所有需要更新的数据（默认为13天数据，今日起）
        List<DirectlyStoreInDO> directlyStoreDOs = directlyStoreRepository.listInByStoreAndDate(storeInfo.getCode(), BigDataCacheUtil.dayStartDate, BigDataCacheUtil.dayUpEndDate);
        List<DirectlyInDO> directlyDOs = salesPlanDirectlyRepository.listInByStoreAndDate(storeInfo.getCode(), BigDataCacheUtil.weekStartDate, BigDataCacheUtil.weekUpEndDate);
        if (CollectionUtils.isEmpty(directlyStoreDOs)) {
            directlyStoreDOs = new ArrayList<>(1);
        }
        if (CollectionUtils.isEmpty(directlyDOs)) {
            directlyDOs = new ArrayList<>(1);
        }
        this.initalUpDayUpWeekData(directlyStoreDOs, directlyDOs, storeInfo, bigDataGeneralInfoDTOs, directlyExecuteInDOs, directlyStoreInDOs, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs);
    }

    private void initalUpDayUpWeekData(List<DirectlyStoreInDO> directlyStoreDOs, List<DirectlyInDO> directlyDOs, StoreInfoDTO storeInfo, List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, List<DirectlyInDO> directlyInDOs) {
        //查询sku信息
        List<SkuInfoDTO> skuInfoDTOS = itemCoreFacade.skuListBySkuCodes(bigDataGeneralInfoDTOs.stream().map(BigDataGeneralInfoDTO::getSkuKey).distinct().collect(Collectors.toList()));
        Map<String, SkuInfoDTO> skuCodeName = this.getSkuInfo(skuInfoDTOS);
        Map<Integer, List<CategorySimpleDTO>> categoryInfo = this.getCategoryInfo(skuInfoDTOS);
        //遍历
        int countStore;
        int countDirect;
        List<DirectlyStoreInDO> tmpStore;
        List<DirectlyInDO> tmpDirect;
        String skuKey;
        BaseInDO baseInDO;
        for (BigDataGeneralInfoDTO bigDataGeneralInfoDTO : bigDataGeneralInfoDTOs) {
            skuKey = bigDataGeneralInfoDTO.getSkuKey();
            //直营预测————门店
            countStore = 0;
            countDirect = 0;
            tmpStore = new ArrayList<>();
            tmpDirect = new ArrayList<>();
            for (DirectlyStoreInDO storeDO : directlyStoreDOs) {
                //如果是同一条sku,默认取十三天为更新数据，第十四条为新增数据 存入集合中
                if (skuKey.equals(storeDO.getSkuCode())) {
                    //更新其同用属性（区域，品类）
                    this.setGeneralInfo(storeDO, skuKey, storeInfo, skuCodeName, categoryInfo);
                    this.setStorePredictValue(storeDO, bigDataGeneralInfoDTO);
                    tmpStore.add(storeDO);
                    countStore++;
                }
            }
            //如果含有更新数据————加入门店第十四天新增数据   执行所有新增数据,否则新增所有天数据
            baseInDO = this.createGeneralDayInDO(skuKey, storeInfo, skuCodeName, categoryInfo);
            if (countStore == 13) {
                directlyStoreInDOs.addAll(tmpStore);
                directlyStoreInDOs.add(this.getNewDirectlyStore(baseInDO, bigDataGeneralInfoDTO.getSalesDayf14()));
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf1(), day1);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf2(), day2);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf3(), day3);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf4(), day4);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf5(), day5);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf6(), day6);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf7(), day7);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf8(), day8);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf9(), day9);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf10(), day10);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf11(), day11);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf12(), day12);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf13(), day13);
                this.getExecuteDayDO(baseInDO, directlyExecuteInDOs, bigDataGeneralInfoDTO.getSalesDayf14(), day14);
            } else {
                //遍历十四天信息
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf1(), day1);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf2(), day2);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf3(), day3);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf4(), day4);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf5(), day5);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf6(), day6);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf7(), day7);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf8(), day8);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf9(), day9);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf10(), day10);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf11(), day11);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf12(), day12);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf13(), day13);
                this.getDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf14(), day14);
            }
            //遍历十三周数据
            for (DirectlyInDO item : directlyDOs) {
                if (skuKey.equals(item.getSkuCode())) {
                    this.setGeneralInfo(item, skuKey, storeInfo, skuCodeName, categoryInfo);
                    this.setDirectlyPredictValue(item, bigDataGeneralInfoDTO);
                    tmpDirect.add(item);
                    countDirect++;
                }
            }
            if (countDirect == 12) {
                directlyInDOs.addAll(tmpDirect);
                directlyInDOs.add(this.getNewDirectly(baseInDO, bigDataGeneralInfoDTO.getSalesWeekf13()));
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf1(), startDate1, endDate1);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf2(), startDate2, endDate2);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf3(), startDate3, endDate3);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf4(), startDate4, endDate4);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf5(), startDate5, endDate5);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf6(), startDate6, endDate6);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf7(), startDate7, endDate7);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf8(), startDate8, endDate8);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf9(), startDate9, endDate9);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf10(), startDate10, endDate10);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf11(), startDate11, endDate11);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf12(), startDate12, endDate12);
                this.getGeneralWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, bigDataGeneralInfoDTO.getSalesWeekf13(), startDate13, endDate13);
            } else {
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf1(), startDate1, endDate1);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf2(), startDate2, endDate2);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf3(), startDate3, endDate3);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf4(), startDate4, endDate4);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf5(), startDate5, endDate5);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf6(), startDate6, endDate6);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf7(), startDate7, endDate7);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf8(), startDate8, endDate8);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf9(), startDate9, endDate9);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf10(), startDate10, endDate10);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf11(), startDate11, endDate11);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf12(), startDate12, endDate12);
                this.getWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf13(), startDate13, endDate13);
            }
        }
    }


    private void getDayDO(BaseInDO baseInDO, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs, BigDecimal sales, Date date) {
        DirectlyExecuteInDO directlyExecuteInDO = bigDataBaseConvertor.baseDOToExecuteDO(baseInDO);
        DirectlyStoreInDO directlyStoreInDO = bigDataBaseConvertor.baseDOToStoreDO(baseInDO);
        //设置日期
        directlyExecuteInDO.setFormulateDate(date);
        directlyStoreInDO.setFormulateDate(date);
        //设置预测量
        directlyExecuteInDO.setForecastSalesAmount(sales);
        directlyStoreInDO.setForecastQty(sales);
        directlyStoreInDO.setConfirmQty(sales);
        directlyStoreInDO.setLastConfirmQty(new BigDecimal("0"));
        directlyStoreInDO.setLastForecastQty(new BigDecimal("0"));
        directlyExecuteInDOs.add(directlyExecuteInDO);
        directlyStoreInDOs.add(directlyStoreInDO);
    }

    private void getWeekDO(BaseInDO baseInDO, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, List<DirectlyInDO> directlyInDOs, BigDecimal sales, Date startDate, Date endDate) {
        DirectlyAccuracyInDO directlyAccuracyInDO = bigDataBaseConvertor.baseDOToAccuracyDO(baseInDO);
        DirectlyDifferinInDO directlyDifferinInDO = bigDataBaseConvertor.baseDOToDifferDO(baseInDO);
        DirectlyInDO directlyInDO = bigDataBaseConvertor.baseDOToDirectDO(baseInDO);
        //设置日期
        directlyAccuracyInDO.setPlanStartDate(startDate);
        directlyAccuracyInDO.setPlanEndDate(endDate);
        directlyDifferinInDO.setPlanStartDate(startDate);
        directlyDifferinInDO.setPlanEndDate(endDate);
        directlyInDO.setPlanStartDate(startDate);
        directlyInDO.setPlanEndDate(endDate);
        //设置预测量
        directlyAccuracyInDO.setPredictedQty(sales);
        directlyDifferinInDO.setSalesForecastQty(sales);
        directlyInDO.setForecastQty(sales);
        //加默认值
        directlyInDO.setLastForecastQty(new BigDecimal("0"));
        directlyAccuracyInDOs.add(directlyAccuracyInDO);
        directlyDifferinInDOs.add(directlyDifferinInDO);
        directlyInDOs.add(directlyInDO);
    }

    private void getGeneralWeekDO(BaseInDO baseInDO, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, BigDecimal sales, Date startDate, Date endDate) {
        DirectlyAccuracyInDO directlyAccuracyInDO = bigDataBaseConvertor.baseDOToAccuracyDO(baseInDO);
        DirectlyDifferinInDO directlyDifferinInDO = bigDataBaseConvertor.baseDOToDifferDO(baseInDO);
        //设置日期
        directlyAccuracyInDO.setPlanStartDate(startDate);
        directlyAccuracyInDO.setPlanEndDate(endDate);
        directlyDifferinInDO.setPlanStartDate(startDate);
        directlyDifferinInDO.setPlanEndDate(endDate);
        //设置预测量
        directlyAccuracyInDO.setPredictedQty(sales);
        directlyDifferinInDO.setSalesForecastQty(sales);
        directlyAccuracyInDOs.add(directlyAccuracyInDO);
        directlyDifferinInDOs.add(directlyDifferinInDO);
    }

    /**
     * 获取（日）通用对象
     *
     * @param skuKey
     * @param storeInfo
     * @param skuCodeName
     * @param categoryInfo
     * @return void
     **/
    private void setGeneralInfo(BaseInDO baseInDO, String skuKey, StoreInfoDTO storeInfo, Map<String, SkuInfoDTO> skuCodeName, Map<Integer, List<CategorySimpleDTO>> categoryInfo) {
        baseInDO.setOpSign(opSign);
        //设置渠道信息
        baseInDO.setChannelCode(BigDataChannelEnum.STORE_DIRECT.getChannelCode());
        baseInDO.setChannelName(BigDataChannelEnum.STORE_DIRECT.getChannelName());
        //设置省市区 门店
        this.setGeneralAreaValue(baseInDO, storeInfo);
        //设置大中小品类
        baseInDO.setSkuCode(skuKey);
        if (skuCodeName.get(skuKey) != null) {
            SkuInfoDTO skuInfoDTO = skuCodeName.get(skuKey);
            baseInDO.setSkuName(skuInfoDTO.getName());
            List<CategorySimpleDTO> categorySimpleDTOS = categoryInfo.get(skuInfoDTO.getCategoryId());
            if (!CollectionUtils.isEmpty(categorySimpleDTOS)) {
                BaseInDO finalDirectlyExecuteInDO = baseInDO;
                categorySimpleDTOS.forEach(subItem -> this.setGeneralCategoryValue(subItem, finalDirectlyExecuteInDO));
            }
        }
    }

    /**
     * 获取（日）通用对象
     *
     * @param skuKey
     * @param storeInfo
     * @param skuCodeName
     * @param categoryInfo
     * @return void
     **/
    private BaseInDO createGeneralDayInDO(String skuKey, StoreInfoDTO storeInfo, Map<String, SkuInfoDTO> skuCodeName, Map<Integer, List<CategorySimpleDTO>> categoryInfo) {
        BaseInDO baseInDO = new BaseInDO();
        baseInDO.setOpSign(opSign);
        //设置渠道信息
        baseInDO.setChannelCode(BigDataChannelEnum.STORE_DIRECT.getChannelCode());
        baseInDO.setChannelName(BigDataChannelEnum.STORE_DIRECT.getChannelName());
        //设置省市区 门店
        this.setGeneralAreaValue(baseInDO, storeInfo);
        //设置大中小品类

        baseInDO.setSkuCode(skuKey);
        if (skuCodeName.get(skuKey) != null) {
            SkuInfoDTO skuInfoDTO = skuCodeName.get(skuKey);
            baseInDO.setSkuName(skuInfoDTO.getName());
            List<CategorySimpleDTO> categorySimpleDTOS = categoryInfo.get(skuInfoDTO.getCategoryId());
            if (!CollectionUtils.isEmpty(categorySimpleDTOS)) {
                BaseInDO finalDirectlyExecuteInDO = baseInDO;
                categorySimpleDTOS.forEach(subItem -> this.setGeneralCategoryValue(subItem, finalDirectlyExecuteInDO));
            }
        }
        return baseInDO;
    }

    /**
     * 设置通用属性 设置品类
     *
     * @param subItem
     * @param baseInDO
     * @return void
     **/
    private void setGeneralCategoryValue(CategorySimpleDTO subItem, BaseInDO baseInDO) {
        Integer level = subItem.getCategoryLevel();
        switch (level) {
            case 2:
                baseInDO.setPriCategoryCode(String.valueOf(subItem.getCategoryCode()));
                baseInDO.setPriCategoryName(subItem.getCategoryName());
                break;
            case 3:
                baseInDO.setSecCategoryCode(String.valueOf(subItem.getCategoryCode()));
                baseInDO.setSecCategoryName(subItem.getCategoryName());
                break;
            case 4:
                baseInDO.setTerCategoryCode(String.valueOf(subItem.getCategoryCode()));
                baseInDO.setTerCategoryName(subItem.getCategoryName());
                break;
            default:
        }
    }

    /**
     * 设置通用属性 设置省市区 门店
     *
     * @param baseInDO
     * @param storeInfo
     * @return void
     **/
    private void setGeneralAreaValue(BaseInDO baseInDO, StoreInfoDTO storeInfo) {
        baseInDO.setProvinceCode(storeInfo.getProvinceCode());
        baseInDO.setProvinceName(storeInfo.getProvinceName());
        baseInDO.setCityCode(storeInfo.getCityCode());
        baseInDO.setCityName(storeInfo.getCityName());
        baseInDO.setCountyCode(storeInfo.getAreaCode());
        baseInDO.setCountyName(storeInfo.getAreaName());
        baseInDO.setStoreCode(storeInfo.getCode());
        baseInDO.setStoreName(storeInfo.getName());
    }

    /**
     * 根据skuInfo获取sku-map信息
     *
     * @param skuInfoDTOS
     * @return void
     **/
    private Map<String, SkuInfoDTO> getSkuInfo(List<SkuInfoDTO> skuInfoDTOS) {
        //根据skuCodes查询skuInfo
        Map<String, SkuInfoDTO> skuCodeName = new HashMap<>();
        if (!CollectionUtils.isEmpty(skuInfoDTOS)) {
            skuCodeName = skuInfoDTOS.stream().collect(Collectors.toMap(SkuInfoDTO::getSkuCode, item -> item));
        }
        return skuCodeName;
    }

    /**
     * 根据skuInfo获取sku品类信息
     *
     * @param skuInfoDTOS
     * @return void
     **/
    private Map<Integer, List<CategorySimpleDTO>> getCategoryInfo(List<SkuInfoDTO> skuInfoDTOS) {
        Map<Integer, List<CategorySimpleDTO>> categoryInfo = new HashMap<>();
        if (!CollectionUtils.isEmpty(skuInfoDTOS)) {
            List<CategorySimpleDTO> categorySimpleDTOS = itemCoreFacade.getAllCategoryByCategoryId(skuInfoDTOS.stream().map(SkuInfoDTO::getCategoryId).distinct().collect(Collectors.toList()));
            categoryInfo = categorySimpleDTOS.stream().collect(Collectors.toMap(CategorySimpleDTO::getId, CategorySimpleDTO::getParentCategoryDTOList));
        }
        return categoryInfo;
    }

    /**
     * 递归分页获取数据
     *
     * @param bigDataGeneralQueryBaseDTO
     * @param bigDataGeneralInfoDTOs
     * @return void
     **/
    private void getBigDataGeneralInfo(BigDataGeneralQueryBaseDTO bigDataGeneralQueryBaseDTO, List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs) {
        bigDataGeneralQueryBaseDTO.setPageNo(bigDataGeneralQueryBaseDTO.getPageNo() + 1);
        List<BigDataGeneralInfoDTO> itemDTOS = cprfCoreFacade.getDayPredictReplenishment(bigDataGeneralQueryBaseDTO);
        if (!CollectionUtils.isEmpty(itemDTOS)) {
            bigDataGeneralInfoDTOs.addAll(itemDTOS);
            if (itemDTOS.size() == CommonConstants.BIG_DATA_PAGE_SIZE) {
                this.getBigDataGeneralInfo(bigDataGeneralQueryBaseDTO, bigDataGeneralInfoDTOs);
            }
        }
    }

    /**
     * 大数据查询实体
     *
     * @param storeCode
     * @param nowDateStr
     * @return {@link BigDataGeneralQueryBaseDTO}
     **/
    private BigDataGeneralQueryBaseDTO getGeneralQueryBaseDTO(String storeCode, String nowDateStr) {
        BigDataGeneralQueryBaseDTO bigDataGeneralQueryBaseDTO = new BigDataGeneralQueryBaseDTO();
        bigDataGeneralQueryBaseDTO.setStartDate(nowDateStr);
        bigDataGeneralQueryBaseDTO.setEndDate(nowDateStr);
        bigDataGeneralQueryBaseDTO.setStore(storeCode);
        bigDataGeneralQueryBaseDTO.setPageNo(0);
        bigDataGeneralQueryBaseDTO.setPageSize(CommonConstants.BIG_DATA_PAGE_SIZE);
        return bigDataGeneralQueryBaseDTO;
    }

    /**
     * 判断是否需要触发周数据任务（默认为每周一才能触发）
     *
     * @param
     * @return {@link boolean}
     **/
    private boolean validWeekJob(Date date) {
        return DateUtil.dayOfWeek(date) == 2;
    }

    /**
     * 插入操作日志
     *
     * @param
     * @return void
     **/
    private void writeOperateLog(Long time) {
        //插入该批次数据日志
        List<OperationLogRecordDO> operationLogRecordDOs = new ArrayList<>(6);
        operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataOperationLog(opSign, OperationDataEnum.DIRECTLY_EXECUTE.getTableType(), time + "ms", OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getDesc()));
        operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataOperationLog(opSign, OperationDataEnum.DIRECTLY_SHOP.getTableType(), time + "ms", OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getDesc()));
        operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataOperationLog(opSign, OperationDataEnum.PLAN_DEMAND.getTableType(), time + "ms", OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getDesc()));
        if (validWeekJob) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataOperationLog(opSign, OperationDataEnum.DIRECTLY_ACCURACY.getTableType(), time + "ms", OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getDesc()));
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataOperationLog(opSign, OperationDataEnum.DIRECTLY_DIFFERIN.getTableType(), time + "ms", OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getDesc()));
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataOperationLog(opSign, OperationDataEnum.PLAN_DIRECTLY.getTableType(), time + "ms", OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_OPERATION_DIRECT_LOG.getDesc()));
        }
        operationLogRecordRepository.batchAddOperationLogRecord(operationLogRecordDOs);
    }

    /**
     * 大数据任务补救接口
     *
     * @param
     * @return void
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remedyBigDataJob() {
        long remedyStartTime = System.currentTimeMillis();
        this.initRemedyCacheData();
        //时间由日志在设置进行状态的接口标记，拉取进行中状态的错误日志
        List<OperationLogRecordDO> operationLogRecordDOS = operationLogRecordRepository.pullRemedialLog(startTime, endTime, OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex(), OperationStatusEnum.PROCESSING.getType());
        if (!CollectionUtils.isEmpty(operationLogRecordDOS)) {
            this.analyzeRemedialLog(operationLogRecordDOS);
        }
        long remedyEndTime = System.currentTimeMillis();
        this.writeOperateLog(remedyEndTime - remedyStartTime);
    }

    private void initRemedyCacheData() {
        this.validWeekJob = validWeekJob(startTime);
        //数据标识
        IdWorker idWorker = new IdWorker();
        opSign = "" + idWorker.getId();
    }

    /**
     * 分析处理日志信息
     *
     * @param operationLogRecordDOS
     * @return void
     **/
    private void analyzeRemedialLog(List<OperationLogRecordDO> operationLogRecordDOS) {
        Map<String, Set<Integer>> storeLogs = new HashMap<>();
        Set<String> storeCodes = new HashSet<>();
        //以门店为单位分组
        String storeCode;
        Set<Integer> set;
        for (OperationLogRecordDO operationLogRecordDO : operationLogRecordDOS) {
            storeCode = operationLogRecordDO.getOpSign();
            storeCodes.add(storeCode);
            if (storeLogs.containsKey(storeCode)) {
                storeLogs.get(storeCode).add(operationLogRecordDO.getOpSource());
            } else {
                set = new HashSet<>();
                set.add(operationLogRecordDO.getOpSource());
                storeLogs.put(storeCode, set);
            }
        }
        Map<String, StoreInfoDTO> storesInfo = redisCacheServiceImpl.getAllStores();
        storeCodes.forEach(item -> {
            BigDataCacheUtil.injectTableFlag(storeLogs.get(item));
            this.handleRemedialStore(storesInfo.get(item));
        });
    }

    /**
     * 处理需要补救的某门店
     *
     * @param storeInfo
     * @return void
     **/
    private void handleRemedialStore(StoreInfoDTO storeInfo) {
        List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs = new ArrayList<>();
        //获取查询条件
        BigDataGeneralQueryBaseDTO bigDataGeneralQueryBaseDTO = this.getGeneralQueryBaseDTO(storeInfo.getCode(), BigDataCacheUtil.nowDate);
        List<DirectlyExecuteInDO> directlyExecuteInDOs = null;
        if (executeFlag) {
            directlyExecuteInDOs = new ArrayList<>();
        }
        List<DirectlyStoreInDO> directlyStoreInDOs = null;
        if (shopFlag) {
            directlyStoreInDOs = new ArrayList<>();
        }
        List<DirectlyAccuracyInDO> directlyAccuracyInDOs = null;
        if (accuracyFlag) {
            directlyAccuracyInDOs = new ArrayList<>();
        }
        List<DirectlyDifferinInDO> directlyDifferinInDOs = null;
        if (differinFlag) {
            directlyDifferinInDOs = null;
        }
        List<DirectlyInDO> directlyInDOs = null;
        if (directlyFlag) {
            directlyInDOs = new ArrayList<>();
        }
        //根据时间段，门店等信息  递归分页获取所有大数据信息
        long handleStartTime = System.currentTimeMillis();
        try {
            this.getBigDataGeneralInfo(bigDataGeneralQueryBaseDTO, bigDataGeneralInfoDTOs);
            if (!CollectionUtils.isEmpty(bigDataGeneralInfoDTOs)) {
                this.getRemedialDayAndWeekResult(storeInfo, bigDataGeneralInfoDTOs, directlyExecuteInDOs, directlyStoreInDOs, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs);
            } else {
                log.warn("\n【大数据补救接口】：门店数据无数据：code {}  name {}", storeInfo.getCode(), storeInfo.getAreaName());
                return;
            }
        } catch (feign.RetryableException retryableException) {
            long handleEndTime = System.currentTimeMillis();
            retryableException.printStackTrace();
            log.error("\n【大数据Job】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + retryableException.getMessage());
            this.writeRemedialErrorLog(storeInfo.getCode(), retryableException.getMessage(), (handleEndTime - handleStartTime), bigDataGeneralInfoDTOs.size());
            return;
        } catch (Exception e) {
            long handleEndTime = System.currentTimeMillis();
            e.printStackTrace();
            log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5004.getMsg());
            this.writeRemedialErrorLog(storeInfo.getCode(), ResponseMsg.FAIL_5004.getMsg(), (handleEndTime - handleStartTime), bigDataGeneralInfoDTOs.size());
            return;
        }
        FutureTask<String> directlyExecuteFutureTask = null;
        FutureTask<String> directlyStoreFutureTask = null;
        FutureTask<String> demandFutureTask = null;
        FutureTask<String> directlyAccuracyFutureTask = null;
        FutureTask<String> directlyDifferinFutureTask = null;
        FutureTask<String> directlyFutureTask = null;
        if (executeFlag) {
            List<DirectlyExecuteInDO> finalDirectlyExecuteInDOs = directlyExecuteInDOs;
            directlyExecuteFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    directlyExecuteServiceImpl.handleRemedialBigData(finalDirectlyExecuteInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.updateBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_EXECUTE.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyExecuteInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()), startTime, endTime);
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(directlyExecuteFutureTask);
        }
        if (shopFlag) {
            List<DirectlyStoreInDO> finalDirectlyStoreInDOs = directlyStoreInDOs;
            directlyStoreFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    directlyStoreServiceImpl.handleRemedialBigData(finalDirectlyStoreInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.updateBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_SHOP.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyStoreInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()), startTime, endTime);
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(directlyStoreFutureTask);
        }
        if (demandFlag) {
            demandFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    demandPlanServiceImpl.handleRemedialBigData(bigDataGeneralInfoDTOs, opSign, storeInfo.getCode(), startDate1);
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.updateBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.PLAN_DEMAND.getTableType(), ResponseMsg.FAIL_5005.getMsg(), bigDataGeneralInfoDTOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()), startTime, endTime);
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(demandFutureTask);
        }
        if (accuracyFlag) {
            List<DirectlyAccuracyInDO> finalDirectlyAccuracyInDOs = directlyAccuracyInDOs;
            directlyAccuracyFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    salesPlanDirectlyAccuracyServiceImpl.handleRemedialBigData(finalDirectlyAccuracyInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.updateBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_ACCURACY.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyAccuracyInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()), startTime, endTime);
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(directlyAccuracyFutureTask);
        }
        if (differinFlag) {
            List<DirectlyDifferinInDO> finalDirectlyDifferinInDOs = directlyDifferinInDOs;
            directlyDifferinFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    salePlanDirectlyDifferinServiceImpl.handleRemedialBigData(finalDirectlyDifferinInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.updateBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.DIRECTLY_DIFFERIN.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyDifferinInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()), startTime, endTime);
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(directlyDifferinFutureTask);
        }
        if (directlyFlag) {
            List<DirectlyInDO> finalDirectlyInDOs = directlyInDOs;
            directlyFutureTask = new FutureTask<>(() -> {
                long sqlStartTime = System.currentTimeMillis();
                try {
                    // salesPlanDirectlyServiceImpl.handleRemedialBigData(finalDirectlyInDOs, storeInfo.getCode());
                } catch (Exception e) {
                    long sqlEndTime = System.currentTimeMillis();
                    e.printStackTrace();
                    log.error("\n【大数据补救接口】：门店数据处理失败：code {}  name {}", storeInfo.getCode(), storeInfo.getName() + " 失败原因：" + ResponseMsg.FAIL_5005.getMsg());
                    operationLogRecordRepository.updateBigDataErrorLog(OperationLogRecordUtil.getBigDataErrorLog(storeInfo.getCode(), OperationDataEnum.PLAN_DIRECTLY.getTableType(), ResponseMsg.FAIL_5005.getMsg(), finalDirectlyInDOs.size(), (sqlEndTime - sqlStartTime) + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()), startTime, endTime);
                    return "failed";
                }
                return "success";
            });
            sonExecutorService.execute(directlyFutureTask);
        }
        String executeFutureResult = "success";
        String storeFutureResult = "success";
        String demandResult = "success";
        String accuracyFutureResult = "success";
        String directlyDifferinFutureResult = "success";
        String directlyFutureResult = "success";
        try {
            if (executeFlag) {
                executeFutureResult = directlyExecuteFutureTask.get();
            }
            if (shopFlag) {
                storeFutureResult = directlyStoreFutureTask.get();
            }
            if (demandFlag) {
                demandResult = demandFutureTask.get();
            }
            if (accuracyFlag) {
                accuracyFutureResult = directlyAccuracyFutureTask.get();
            }
            if (differinFlag) {
                directlyDifferinFutureResult = directlyDifferinFutureTask.get();
            }
            if (directlyFlag) {
                directlyFutureResult = directlyFutureTask.get();
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        if ("success".equals(executeFutureResult) && "success".equals(storeFutureResult) && "success".equals(demandResult) && "success".equals(accuracyFutureResult) && "success".equals(directlyDifferinFutureResult) && "success".equals(directlyFutureResult)) {
            log.info("\n【大数据补救接口】：门店数据处理成功：code {}  name {}", storeInfo.getCode(), storeInfo.getName());
        }
    }

    private void getRemedialDayAndWeekResult(StoreInfoDTO storeInfo, List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, List<DirectlyInDO> directlyInDOs) {
        //直营预测——执行 根据门店和日期获取所有需要更新的数据（默认为13天数据，今日起）
        List<DirectlyStoreInDO> directlyStoreDOs = null;
        if (shopFlag) {
            directlyStoreDOs = directlyStoreRepository.listInByStoreAndDate(storeInfo.getCode(), BigDataCacheUtil.dayStartDate, BigDataCacheUtil.dayUpEndDate);
        }
        List<DirectlyInDO> directlyDOs = null;
        if (directlyFlag) {
            directlyDOs = salesPlanDirectlyRepository.listInByStoreAndDate(storeInfo.getCode(), BigDataCacheUtil.weekStartDate, BigDataCacheUtil.weekUpEndDate);
        }
        //如果存在不为null的情况，那么必然需要更新上次量操作
        if (CollectionUtils.isEmpty(directlyStoreDOs)) {
            directlyStoreDOs = new ArrayList<>(1);
        }
        if (CollectionUtils.isEmpty(directlyDOs)) {
            directlyDOs = new ArrayList<>(1);
        }
        this.initalRemedialUpDayUpWeekData(directlyStoreDOs, directlyDOs, storeInfo, bigDataGeneralInfoDTOs, directlyExecuteInDOs, directlyStoreInDOs, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs);
    }


    private void initalRemedialUpDayUpWeekData(List<DirectlyStoreInDO> directlyStoreDOs, List<DirectlyInDO> directlyDOs, StoreInfoDTO storeInfo, List<BigDataGeneralInfoDTO> bigDataGeneralInfoDTOs, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, List<DirectlyInDO> directlyInDOs) {
        //查询sku信息
        List<SkuInfoDTO> skuInfoDTOS = itemCoreFacade.skuListBySkuCodes(bigDataGeneralInfoDTOs.stream().map(BigDataGeneralInfoDTO::getSkuKey).distinct().collect(Collectors.toList()));
        Map<String, SkuInfoDTO> skuCodeName = this.getSkuInfo(skuInfoDTOS);
        Map<Integer, List<CategorySimpleDTO>> categoryInfo = this.getCategoryInfo(skuInfoDTOS);
        //遍历
        int countStore = 0;
        int countDirect = 0;
        List<DirectlyStoreInDO> tmpStore = null;
        List<DirectlyInDO> tmpDirect = null;
        String skuKey;
        BaseInDO baseInDO;
        for (BigDataGeneralInfoDTO bigDataGeneralInfoDTO : bigDataGeneralInfoDTOs) {
            skuKey = bigDataGeneralInfoDTO.getSkuKey();
            baseInDO = this.createGeneralDayInDO(skuKey, storeInfo, skuCodeName, categoryInfo);
            //直营预测————门店
            if (shopFlag) {
                countStore = 0;
                tmpStore = new ArrayList<>();
                for (DirectlyStoreInDO storeDO : directlyStoreDOs) {
                    //如果是同一条sku,默认取十三天为更新数据，第十四条为新增数据 存入集合中
                    if (skuKey.equals(storeDO.getSkuCode())) {
                        //存入门店更新后的新增数据
                        this.setGeneralInfo(storeDO, skuKey, storeInfo, skuCodeName, categoryInfo);
                        this.setStorePredictValue(storeDO, bigDataGeneralInfoDTO);
                        tmpStore.add(storeDO);
                        countStore++;
                    }
                }
            }
            //如果含有更新数据————加入门店第十四天新增数据   执行所有新增数据,否则新增所有天数据
            if (countStore == 13) {
                directlyStoreInDOs.addAll(tmpStore);
                directlyStoreInDOs.add(this.getNewDirectlyStore(baseInDO, bigDataGeneralInfoDTO.getSalesDayf14()));
            }
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf1(), day1, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf2(), day2, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf3(), day3, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf4(), day4, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf5(), day5, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf6(), day6, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf7(), day7, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf8(), day8, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf9(), day9, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf10(), day10, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf11(), day11, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf12(), day12, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf13(), day13, countStore != 13);
            this.getRemedialDayDO(baseInDO, directlyExecuteInDOs, directlyStoreInDOs, bigDataGeneralInfoDTO.getSalesDayf14(), day14, countStore != 13);
            if (directlyFlag) {
                countDirect = 0;
                tmpDirect = new ArrayList<>();
                //遍历十三周数据
                for (DirectlyInDO item : directlyDOs) {
                    if (skuKey.equals(item.getSkuCode())) {
                        this.setGeneralInfo(item, skuKey, storeInfo, skuCodeName, categoryInfo);
                        this.setDirectlyPredictValue(item, bigDataGeneralInfoDTO);
                        tmpDirect.add(item);
                        countDirect++;
                    }
                }
            }
            if (countDirect == 12) {
                directlyInDOs.addAll(tmpDirect);
                directlyInDOs.add(this.getNewDirectly(baseInDO, bigDataGeneralInfoDTO.getSalesWeekf13()));
            }
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf1(), startDate1, endDate1, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf2(), startDate2, endDate2, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf3(), startDate3, endDate3, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf4(), startDate4, endDate4, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf5(), startDate5, endDate5, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf6(), startDate6, endDate6, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf7(), startDate7, endDate7, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf8(), startDate8, endDate8, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf9(), startDate9, endDate9, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf10(), startDate10, endDate10, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf11(), startDate11, endDate11, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf12(), startDate12, endDate12, countDirect != 12);
            this.getRemedialWeekDO(baseInDO, directlyAccuracyInDOs, directlyDifferinInDOs, directlyInDOs, bigDataGeneralInfoDTO.getSalesWeekf13(), startDate13, endDate13, countDirect != 12);
        }
    }

    private void getRemedialDayDO(BaseInDO baseInDO, List<DirectlyExecuteInDO> directlyExecuteInDOs, List<DirectlyStoreInDO> directlyStoreInDOs, BigDecimal sales, Date date, boolean flagStore) {
        if (executeFlag) {
            DirectlyExecuteInDO directlyExecuteInDO = bigDataBaseConvertor.baseDOToExecuteDO(baseInDO);
            directlyExecuteInDO.setFormulateDate(date);
            //设置预测量
            directlyExecuteInDO.setForecastSalesAmount(sales);
            directlyExecuteInDOs.add(directlyExecuteInDO);
        }
        if (shopFlag && flagStore) {
            DirectlyStoreInDO directlyStoreInDO = bigDataBaseConvertor.baseDOToStoreDO(baseInDO);
            //设置日期
            directlyStoreInDO.setFormulateDate(date);
            directlyStoreInDO.setForecastQty(sales);
            directlyStoreInDO.setConfirmQty(sales);
            directlyStoreInDO.setLastConfirmQty(new BigDecimal("0"));
            directlyStoreInDO.setLastForecastQty(new BigDecimal("0"));
            directlyStoreInDOs.add(directlyStoreInDO);
        }
    }

    private void getRemedialWeekDO(BaseInDO baseInDO, List<DirectlyAccuracyInDO> directlyAccuracyInDOs, List<DirectlyDifferinInDO> directlyDifferinInDOs, List<DirectlyInDO> directlyInDOs, BigDecimal sales, Date startDate, Date endDate, boolean flagDirect) {
        if (accuracyFlag) {
            DirectlyAccuracyInDO directlyAccuracyInDO = bigDataBaseConvertor.baseDOToAccuracyDO(baseInDO);
            //设置日期
            directlyAccuracyInDO.setPlanStartDate(startDate);
            directlyAccuracyInDO.setPlanEndDate(endDate);
            //设置预测量
            directlyAccuracyInDO.setPredictedQty(sales);
            directlyAccuracyInDOs.add(directlyAccuracyInDO);
        }
        if (differinFlag) {
            DirectlyDifferinInDO directlyDifferinInDO = bigDataBaseConvertor.baseDOToDifferDO(baseInDO);
            directlyDifferinInDO.setPlanStartDate(startDate);
            directlyDifferinInDO.setPlanEndDate(endDate);
            directlyDifferinInDO.setSalesForecastQty(sales);
            directlyDifferinInDOs.add(directlyDifferinInDO);
        }
        if (directlyFlag && flagDirect) {
            DirectlyInDO directlyInDO = bigDataBaseConvertor.baseDOToDirectDO(baseInDO);
            directlyInDO.setPlanStartDate(startDate);
            directlyInDO.setPlanEndDate(endDate);
            directlyInDO.setForecastQty(sales);
            //加默认值
            directlyInDO.setLastForecastQty(new BigDecimal("0"));
            directlyInDOs.add(directlyInDO);
        }
    }

    private void writeRemedialErrorLog(String storeCode, String msg, long time, int size) {
        List<OperationLogRecordDO> operationLogRecordDOs = new ArrayList<>(6);
        if (executeFlag) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_EXECUTE.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        if (shopFlag) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_SHOP.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        if (accuracyFlag) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_ACCURACY.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        if (differinFlag) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.DIRECTLY_DIFFERIN.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        if (directlyFlag) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.PLAN_DIRECTLY.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        if (demandFlag) {
            operationLogRecordDOs.add(OperationLogRecordUtil.getBigDataErrorLog(storeCode, OperationDataEnum.PLAN_DEMAND.getTableType(), msg, size, time + "ms", OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex().toString(),OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getDesc()));
        }
        operationLogRecordRepository.batchUpdateBigDataErrorLog(operationLogRecordDOs, startTime, endTime);
    }
}
